#if VS_TESSELLATION

struct HS_CONTROL_POINT_OUTPUT_GLOWPASS
{
	hsControlPointShared controlPoint;

	float4 maskTC   : TEXCOORDN;

#if %_RT_DECAL_TEXGEN_2D
	float3 DistAtten   : TEXCOORDN;
#endif

#if %VERTCOLORS
	float3 Color    : COLOR0;
#endif
};

HS_CONSTANT_DATA_OUTPUT GlowPassConstantsHS(InputPatch<vert2fragGlow, 3> p, uint PatchID : SV_PrimitiveID)
{
	const float3 vP0 = p[0].vView.xyz + g_VS_WorldViewPos.xyz;
	const float3 vP1 = p[1].vView.xyz + g_VS_WorldViewPos.xyz;
	const float3 vP2 = p[2].vView.xyz + g_VS_WorldViewPos.xyz;
	HS_CONSTANT_DATA_OUTPUT output = CommonConstantsHS(vP0, vP1, vP2, g_VS_WorldViewPos.xyz, g_VS_WorldViewPos.xyz, PatchID);

	return output;
}

[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("GlowPassConstantsHS")]
[maxtessfactor(MAX_TESS_FACTOR)]
HS_CONTROL_POINT_OUTPUT_GLOWPASS Common_GlowPassHS(InputPatch<vert2fragGlow, 3> inputPatch, uint uCPID : SV_OutputControlPointID)
{
	HS_CONTROL_POINT_OUTPUT_GLOWPASS	output = (HS_CONTROL_POINT_OUTPUT_GLOWPASS)0;

	output.controlPoint.vView   = inputPatch[uCPID].vView;
	output.controlPoint.vNormal = inputPatch[uCPID].vNormal.xyz;
	output.controlPoint.vBaseTC = inputPatch[uCPID].baseTC;

	output.maskTC               = inputPatch[uCPID].maskTC;

#if %_RT_DECAL_TEXGEN_2D
	output.DistAtten            = inputPatch[uCPID].DistAtten;
#endif

#if %VERTCOLORS
	output.Color                = inputPatch[uCPID].Color;
#endif

	return output;
}

///////////////// domain shader //////////////////

void FillEvalInput_Glow(in HS_CONTROL_POINT_OUTPUT_GLOWPASS triPatch[3], in HS_CONSTANT_DATA_OUTPUT hsConstData, in float3 vBaryCoords, inout CommonEvaluationInputDS evalInput)
{
	evalInput.vBaryCoords = vBaryCoords;
	FillEvalInputControlPoint(triPatch[0].controlPoint, triPatch[1].controlPoint, triPatch[2].controlPoint, hsConstData, evalInput);
	evalInput.bRelativePos = true;
#if %VERTCOLORS
	FillEvalInputColor(triPatch[0].Color.rgbb, triPatch[1].Color.rgbb, triPatch[2].Color.rgbb, evalInput);
#endif
	evalInput.vViewPos = g_VS_WorldViewPos.xyz;
}

void ProcessEvalOutput(in CommonEvaluationOutputDS evalOutput, inout vert2fragGlow dsOutput)
{
	dsOutput.baseTC = evalOutput.vBaseTC;

#if %VERTCOLORS
	dsOutput.Color = evalOutput.vColor.rgb;
#endif

	dsOutput.HPosition = mul(g_VS_ViewProjZeroMatr, float4(evalOutput.vPos.xyz, 1));
}

[domain("tri")]
vert2fragGlow Common_GlowPassDS( HS_CONSTANT_DATA_OUTPUT hsConstData, float3 vBaryCoords : SV_DomainLocation, const OutputPatch<HS_CONTROL_POINT_OUTPUT_GLOWPASS, 3> TrianglePatch )
{
	vert2fragGlow output = (vert2fragGlow)0;

	CommonEvaluationInputDS evalInput = (CommonEvaluationInputDS)0;
	FillEvalInput_Glow(TrianglePatch, hsConstData, vBaryCoords, evalInput);

	CommonEvaluationOutputDS evalOutput;
	Evaluate(evalInput, evalOutput);
	ProcessEvalOutput(evalOutput, output);

	output.maskTC = EvalVec(TrianglePatch[0].maskTC, TrianglePatch[1].maskTC, TrianglePatch[2].maskTC, vBaryCoords);

#if %_RT_DECAL_TEXGEN_2D
	 output.DistAtten = EvalVec(TrianglePatch[0].DistAtten, TrianglePatch[1].DistAtten, TrianglePatch[2].DistAtten, vBaryCoords);
#endif 

	return output;
}

#endif